home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C ++ / Code Resources / Windows 95 MDEF 2.0.1 / Sourcery / Windows95 MDEF.cpp < prev   
Encoding:
C/C++ Source or Header  |  1997-08-18  |  20.2 KB  |  664 lines  |  [TEXT/CWIE]

  1. /*
  2.     Windows95 MDEF Emulator
  3.     Version 2.0
  4.  
  5.     Evolved from the NeXT MDEF
  6.     written on Jan. 17, 1994 (Right after the Northridge earthquake—whew!!)
  7.  
  8.     by Hiep Dam, From The Witches' Brew
  9.     Contact: America Online -> StarLabs
  10.              Internet       -> starlabs@aol.com
  11.  
  12.  
  13.     FREE! FREE! FREE!
  14.     This code & MDEF are in the public domain.
  15.  
  16.  
  17.     Usage:
  18.     
  19.         Default resource id of MDEF: 1972
  20.         Go into ResEdit and edit the menu's MDEF ID to 1972. That's it!
  21.  
  22.         If you just use the MDEF by itself, by default the menus will have
  23.         a nice 3D grayish look. Your average 3D color customized look...
  24.         Nice, but boring to some.
  25.         
  26.         ...
  27.  
  28.         However, things get more exciting if you add custom resources.
  29.         The MDEF looks for any resources of type 'MnuT' ("Menu template")
  30.         that are the same resource id as the menu. If it doesn't find any
  31.         then it looks for one with the default id of 0. Barring that it
  32.         uses the default look mentioned above.
  33.         
  34.         The 'MnuT' resources define how the Windows95 MDEF colors and draws
  35.         the menu. You specify 3 RGB colors: the menu background color, the
  36.         menu hilite (light) color, and the menu shadow (dark) color. The
  37.         shadow color will also be used to hilite the selected menu item for
  38.         that menu. You must also specify in the 'MnuT' resource the menu's
  39.         font, font size, and font face.
  40.         
  41.         The use of 'MnuT' makes the Windows95 MDEF very versatile and gives
  42.         you control over the color scheme and font appearance of your
  43.         menus. Note: 'mctb' resources are not supported; they're
  44.         really too overblown for my tastes.
  45.  
  46.  
  47.     Notes:
  48.  
  49.     What this MDEF supports:
  50.         * Menu items as submenu items (i.e. points to a submenu w/ a triangle)
  51.         * as a submenu itself
  52.         * cmd-keys
  53.         * item marks
  54.         * item text styles
  55.     
  56.     What this MDEF does not support:
  57.         * meta-characters and parsing menu item text for such characters
  58.         * icons, sicns, reduced icons, cicns. In other words, no icons.
  59.         * scrolling. If you have a lot of menu items, the ones near the
  60.           bottom of the screen will be clipped. Don't use too many items!
  61.     
  62.  
  63.  
  64.     1) This MDEF makes several IMPORTANT *assumptions* about the environment
  65.         it's running on. Running in an incorrect environment will result
  66.         in messy crashes.
  67.             a) Color Quickdraw is present. It uses RGBColors to draw the menu,
  68.                 not the old-style 8-color Quickdraw model. There is no check
  69.                 to see if Color Quickdraw is available or not. If the MDEF is
  70.                 running in a b&w environment, there will be an "unimplemented
  71.                 trap" error. The MDEF absolutely requires Color QD.
  72.             b) System 7 is present.
  73.  
  74.     2) The original portions of the NeXT MDEF were derived from an example MDEF
  75.         included in THINK Reference. See "Custom Menus" in the Menu Manager
  76.         section. The code has changed significantly with the move over to
  77.         a Windows95 look from the NeXT look.
  78.     
  79.     3) I think this code is a good place to start when writing your own
  80.         customized MDEFs. Note that to write MDEFs which support more than just
  81.         the most rudimentary stuff (i.e. more than plain text) things can get
  82.         hairy pretty fast. You have to take into account submenus, item
  83.         marks, command keys, large icons, small icons, and so on. And if
  84.         you want to support extensions such as other modifier keys like
  85.         control, shift, and option keys; whew, it's a lot of work. I
  86.         don't envy the author of the Mercutio MDEF...
  87.  
  88.  
  89.     Version History:
  90.     1.0: Initial release (limited to a source code CD-ROM); was NeXT MDEF
  91.  
  92.     2.0: 11/28/95
  93.          Modified mdef -> now Windows95 MDEF. Boxy menu item look removed
  94.          (admittedly it had looked rather tacky).
  95.          Pretty much complete overhaul. Gotta say it: my old code was
  96.          pretty messy...
  97.  
  98.     2.0.1: 12/1/95
  99.         Fixed submenu problem partially by using mbSaveLoc. What a
  100.         pain! I have to muck around low-memory system globals JUST
  101.         TO MAKE THE DARN THING WORK! Most of the stuff can be found
  102.         in the mChooseMsg handler.
  103.         Also "fixed" popup menu problem using a sample MDEF written
  104.         by Ken Worley. Thanks Ken! (The popup menu still might pop
  105.         up incorrectly if the system 7 popup menu cdef is used and
  106.         the menu is placed near the edges of the monitor. I figure
  107.         it's the system's fault - not mine). Stuff can be found in
  108.         the mPopUpMsg handler.
  109.  
  110. */
  111.  
  112. // ---------------------------------------------------------------------------
  113.  
  114. #include <Types.h>
  115. #include <Memory.h>
  116. #include <Quickdraw.h>
  117. #include <Fonts.h>
  118. #include <ToolUtils.h>
  119. #include <Icons.h>
  120. #include <Controls.h>
  121. #include <Gestalt.h>
  122. #include <Resources.h>
  123.  
  124. #include "DrawMenuItem.h"
  125. #include "GetDominantDevice.h"
  126.  
  127. // ---------------------------------------------------------------------------
  128.  
  129. /*
  130.     Writing an MDEF which properly uses submenus (among other things)
  131.     requires that we mess with undocumented system globals, a practice
  132.     that will probably blow up in our faces in the future. Set to
  133.     0 when that time comes, recompile, and voila! Problems should then
  134.     be fixed if we have written the MDEF well.
  135. */
  136.  
  137. #define USE_UNDOCUMENTED_STUFF    1
  138.  
  139. // ---------------------------------------------------------------------------
  140.  
  141. // Some prototypes
  142. pascal void main(short msg, MenuHandle whichMenu, Rect *menuRect,
  143.         Point hitPt, short *itemID);
  144.  
  145.  
  146. static void FillInColor(
  147.     RGBColor *theColor,
  148.     unsigned short r,
  149.     unsigned short g,
  150.     unsigned short b);
  151. static void InitMenuData(short menuID, MDEFstuff *data);
  152.  
  153. static short GetMenuItemHeight();
  154. static short GetMenuHeight(short numItems);
  155. static short FindMenuItem(MenuHandle whichMenu, Rect *menuRect, Point hitPt);
  156. static short GetMenuWidth(MenuHandle whichMenu, short numItems, MDEFstuff *mdefData);
  157.  
  158. static void DoSizeMsg(MenuHandle whichMenu, Rect *menuRect, MDEFstuff *mdefData);
  159. static void DoPopUpMsg(
  160.     MenuHandle    whichMenu,
  161.     Rect        *menuRect,
  162.     short        menuItem,
  163.     Point        hitPt,
  164.     MDEFstuff    *mdefData);
  165. static void DoDrawMsg(MenuHandle whichMenu, Rect *menuRect, MDEFstuff *mdefData);
  166. static void DoChooseMsg(
  167.     MenuHandle    whichMenu,
  168.     Rect        *menuRect,
  169.     Point        hitPt,
  170.     short        *itemID,
  171.     MDEFstuff    *mdefData);
  172.  
  173.  
  174. // ----------------------------------------------------------------------
  175.  
  176. /*
  177.     Main.
  178.  
  179.     This is the entrypoint for the MDEF. So what does that mean? Simply
  180.     this is the function that will be called when the MDEF is used.
  181.     It checks what is the current message sent to it, case goes
  182.     thru a switch statement to find the correct handler for the msg.
  183. */
  184.  
  185. pascal void main(short msg, MenuHandle whichMenu, Rect *menuRect, Point hitPt,
  186.                         short *theMenuItem) {
  187.     MDEFstuff menuData;
  188.     GrafPtr curPort;
  189.     short saveFont, saveSize, saveFace, saveMode;
  190.     RGBColor saveFore, saveBack;
  191.     PenState savePen;
  192.     
  193.     // We're implicitly drawing into the Window Manager port, so make
  194.     // sure we save the important settings so we can restore them later on.
  195.     GetPort(&curPort);
  196.     saveFont = curPort->txFont;
  197.     saveSize = curPort->txSize;
  198.     saveFace = curPort->txFace;
  199.     saveMode = curPort->txMode;
  200.     GetForeColor(&saveFore);
  201.     GetBackColor(&saveBack);
  202.     GetPenState(&savePen);
  203.  
  204.     InitMenuData((**whichMenu).menuID, &menuData);
  205.     TextFont(menuData.params.menuFont);
  206.     TextSize(menuData.params.menuSize);
  207.     TextFace(menuData.params.menuFace);
  208.  
  209.     switch (msg) {
  210.         case mDrawMsg: {
  211.             DoDrawMsg(whichMenu, menuRect, &menuData);
  212.         } break;
  213.     
  214.         case mChooseMsg: {
  215.             DoChooseMsg(whichMenu, menuRect, hitPt, theMenuItem, &menuData);
  216.         } break;
  217.     
  218.         case mSizeMsg: {
  219.             DoSizeMsg(whichMenu, menuRect, &menuData);
  220.         } break;
  221.     
  222.         case mPopUpMsg: {
  223.             DoPopUpMsg(whichMenu, menuRect, *theMenuItem, hitPt, &menuData);
  224.         } break;
  225.     }    // END switch
  226.  
  227.     // Polite manners: if we changed the font, restore the system font
  228.     // upon exiting...
  229.     TextFont(saveFont);
  230.     TextSize(saveSize);
  231.     TextFace(saveFace);
  232.     TextMode(saveMode);
  233.     RGBForeColor(&saveFore);
  234.     RGBBackColor(&saveBack);
  235.     SetPenState(&savePen);
  236. } // END main
  237.  
  238. // ----------------------------------------------------------------------
  239.  
  240. /*
  241.     IsItemDisabled.
  242.  
  243.     Finds out whether the given menu item is disabled or not. Note though
  244.     that we also have to check if the *entire* menu is disabled or not, in
  245.     addition to the menu item. We do this by checking bit 0 of the
  246.     enableFlags field in the menuInfo structure of a menu.
  247.     This is done because the menu can be disabled regardless whether
  248.     the menu item is enabled or not - the menu takes precedence over
  249.     the menu items.
  250.     
  251.     With the advent of Copland, this part will be incompatible. Hopefully
  252.     accessors for a menu item's enabled/disabled state will be available.
  253. */
  254.  
  255. Boolean IsItemDisabled(MenuHandle whichMenu, short whichItem) {
  256.     if (whichItem > 31)
  257.         return(false);    // Items > 31 always enabled
  258.     
  259.     Str255 itemText;
  260.     GetItem(whichMenu, whichItem, itemText);
  261.     if (itemText[1] == kDividerChar)
  262.         return(true);    // Divider menu items always disabled.
  263.  
  264.     return(!BitTst(&(**whichMenu).enableFlags, 31 - whichItem) ||
  265.            !BitTst(&(**whichMenu).enableFlags, 31 - 0));
  266. } // END IsItemDisabled
  267.  
  268. // ----------------------------------------------------------------------
  269.  
  270. /*
  271.     GetMenuItemHeight.
  272.  
  273.     Get the height of any single menu item. If you wish to add icons
  274.     to your menu, you'll have to change this to accomodate larger icons.
  275.     This simply calls _GetFontInfo.
  276. */
  277.  
  278. short GetMenuItemHeight() {
  279.     FontInfo theInfo;
  280.     GetFontInfo(&theInfo);
  281.     // Account for padding for both top and bottom (that's why we're *2)
  282.     return(theInfo.ascent + (kHeightPadding + kHeightPadding));
  283. } // END GetMenuItemHeight
  284.  
  285. // ----------------------------------------------------------------------
  286.  
  287. /*
  288.     GetMenuHeight.
  289.  
  290.     Gets the height of a single menu item, and finds the height
  291.     of the whole menu by multiplying a single menu item height
  292.     by the number of menu items.
  293. */
  294.  
  295. short GetMenuHeight(short numItems) {
  296.     return((numItems * GetMenuItemHeight()) + (kRectPadding + kRectPadding));
  297. } // END GetMenuHeight
  298.  
  299. // ----------------------------------------------------------------------
  300.  
  301. /*
  302.     GetMenuWidth.
  303.  
  304.     Gets the width of the entire menu, by finding the width of the
  305.     widest menu item in the menu. Polls each menu item for its width,
  306.     keeping track of the largest width.
  307.  
  308.     Accounts for submenu "triangles" mini-icon and cmd-keys in menu
  309.     item width.
  310. */
  311.  
  312. short GetMenuWidth(MenuHandle whichMenu, short numItems, MDEFstuff *mdefData) {
  313.     Str255 itemText;
  314.     short maxLength = 0;
  315.     short curLength = 0;
  316.     short theChar;
  317.     short cmdWidth;
  318.     short checkWidth;
  319.     Style style;
  320.     Boolean hasCmdKeys = false;
  321.     
  322.     checkWidth = CharWidth(kCheckMarkChar) +
  323.         kItemMarkPadding + kItemMarkPadding;        // 4 = left & right padding
  324.     cmdWidth = CharWidth(kCmdKeyChar);            // "Cmd" key clover character
  325.     cmdWidth += CharWidth(kWidestChar);                // "W" is widest character in the bunch
  326.  
  327.     for (short i = 1; i <= numItems; i++) {
  328.         GetItem(whichMenu, i, itemText);
  329.         GetItemStyle(whichMenu, i, &style);
  330.         if (style)
  331.             TextFace(style);
  332.         else
  333.             TextFace((mdefData->params).menuFace);
  334.         curLength = StringWidth(itemText);
  335.  
  336.         GetItemCmd(whichMenu, i, &theChar);
  337.         if (theChar != 0)
  338.             hasCmdKeys = true;
  339.  
  340.         curLength += checkWidth;
  341.  
  342.         if (curLength > maxLength)
  343.             maxLength = curLength;
  344.     }
  345.  
  346.     // Padding is both to left and right of cmdKey+char itself.
  347.     if (hasCmdKeys)
  348.         maxLength += (cmdWidth + (kCmdKeyPadding + kCmdKeyPadding));
  349.  
  350.     return(maxLength + (kWidthPadding + kWidthPadding));
  351. } // END GetMenuWidth
  352.  
  353. // ----------------------------------------------------------------------
  354.  
  355. /*
  356.     GetMenuItemRect.
  357.     Determine rect of menu item. Pretty obvious.
  358. */
  359.  
  360. void GetMenuItemRect(Rect *menuRect, Rect *itemRect, short whichItem) {
  361.     short oneHeight = GetMenuItemHeight();
  362.  
  363.     //InsetRect(menuRect, kRectPadding, kRectPadding);
  364.     itemRect->left   = menuRect->left;
  365.     itemRect->right  = menuRect->right;
  366.     itemRect->top    = menuRect->top + (oneHeight * (whichItem - 1));
  367.     itemRect->bottom = itemRect->top + oneHeight;
  368.     //InsetRect(menuRect, -kRectPadding, -kRectPadding);
  369. } // END GetMenuItemRect
  370.  
  371. // ---------------------------------------------------------------------------
  372.  
  373. // FindMenuItem.
  374. // Given a point, find if this point is within the rect of any menu
  375. // item. If so, return the item, else 0.
  376.  
  377. short FindMenuItem(MenuHandle whichMenu, Rect *menuRect, Point hitPt) {
  378.     Rect itemRect;
  379.     short itemCount = CountMItems(whichMenu);
  380.     
  381.     if (!PtInRect(hitPt, menuRect))
  382.         return(0);
  383.  
  384.     for (short i = 1; i <= itemCount; i++) {
  385.         GetMenuItemRect(menuRect, &itemRect, i);
  386.         if (PtInRect(hitPt, &itemRect)) {
  387.             return(i);
  388.         }
  389.     }
  390.     return(0);
  391. } // END FindMenuItem
  392.  
  393. // ---------------------------------------------------------------------------
  394. // ---------------------------------------------------------------------------
  395.  
  396. /*
  397.     DoSizeMsg.
  398.     Even more obvious (más o menos). Calls others to do the job.
  399. */
  400.  
  401. void DoSizeMsg(MenuHandle whichMenu, Rect *menuRect, MDEFstuff *mdefData) {
  402.     short itemCount = CountMItems(whichMenu);
  403.  
  404.     (**whichMenu).menuWidth  = GetMenuWidth(whichMenu, itemCount, mdefData);
  405.     (**whichMenu).menuHeight = GetMenuHeight(itemCount);
  406. } // END DoSizeMsg
  407.  
  408. // ----------------------------------------------------------------------
  409.  
  410. enum {
  411.     kPopupMargin = 4
  412. };
  413.  
  414. void DoPopUpMsg(
  415.     MenuHandle    whichMenu,
  416.     Rect        *menuRect,
  417.     short        menuItem,
  418.     Point        hitPt,
  419.     MDEFstuff    *mdefData) {
  420.     /*
  421.         Note how hitPt.h and hitPt.v are matched to top and left.
  422.         Not intuitive! Another quirk in the OS.
  423.     */
  424.     
  425.     short itemCount = CountMItems(whichMenu);
  426.     menuRect->top = hitPt.h - (menuItem * GetMenuItemHeight());
  427.     menuRect->left = hitPt.v;
  428.     // Get the width & height
  429.     DoSizeMsg(whichMenu, menuRect, mdefData);
  430.     menuRect->right = menuRect->left + (**whichMenu).menuWidth;
  431.     menuRect->bottom = menuRect->top + (**whichMenu).menuHeight;
  432.     
  433.     Rect deviceBounds;
  434.     deviceBounds = (**GetDominantDevice(menuRect)).gdRect;
  435.     if (menuRect->bottom > (deviceBounds.bottom-kPopupMargin))
  436.         OffsetRect(menuRect, 0, (deviceBounds.bottom-kPopupMargin) - menuRect->bottom);
  437.     
  438.     if (menuRect->right > (deviceBounds.right-kPopupMargin))
  439.         OffsetRect(menuRect, (deviceBounds.right-kPopupMargin) - menuRect->right, 0);
  440.     
  441.     if (menuRect->top < (deviceBounds.top+kPopupMargin))
  442.         OffsetRect(menuRect, 0, (deviceBounds.top+kPopupMargin) - menuRect->top);
  443.     
  444.     if (menuRect->left < (deviceBounds.left+kPopupMargin))
  445.         OffsetRect(menuRect, (deviceBounds.left+kPopupMargin) - menuRect->left, 0);
  446. } // END DoPopUpMsg
  447.  
  448. // ---------------------------------------------------------------------------
  449.  
  450. /*
  451.     DoDrawMsg.
  452.     Erases the entire menu, and calls each menu item individually to
  453.     draw itself.
  454. */
  455.  
  456. void DoDrawMsg(MenuHandle whichMenu, Rect *menuRect, MDEFstuff *mdefData) {
  457.     short itemCount = CountMItems(whichMenu);
  458.  
  459.     RGBBackColor(&(mdefData->params).menuBkgndColor);
  460.     EraseRect(menuRect);
  461.  
  462.     PenSize(1, 1);
  463.     InsetRect(menuRect, 1, 1);
  464.     RGBForeColor(&(mdefData->params).menuHiliteColor);
  465.     MoveTo(menuRect->left, menuRect->top);
  466.     LineTo(menuRect->right, menuRect->top);
  467.     MoveTo(menuRect->left, menuRect->top);
  468.     LineTo(menuRect->left, menuRect->bottom);
  469.     RGBForeColor(&(mdefData->params).menuShadowColor);
  470.     MoveTo(menuRect->right, menuRect->bottom);
  471.     LineTo(menuRect->right, menuRect->top);
  472.     MoveTo(menuRect->right, menuRect->bottom);
  473.     LineTo(menuRect->left, menuRect->bottom);
  474.  
  475.     for (short i = 1; i <= itemCount; i++) {
  476.         DrawMenuItem(whichMenu, menuRect, i, kMenuUnhilited, mdefData);
  477.     }
  478.     InsetRect(menuRect, -1, -1);
  479. } // END DoDrawMsg
  480.  
  481. // ----------------------------------------------------------------------
  482.  
  483. #pragma mark UNDOCUMENTED DATA!
  484.  
  485. #if USE_UNDOCUMENTED_STUFF
  486. /*
  487.     Define some undocumented low-memory system globals. You can bet
  488.     yer dollar this will break in future releases of the MacOS, but
  489.     doing this is a necessary evil, as it is required to make the
  490.     MDEF work __properly__ with submenus.
  491. */
  492.  
  493. // mbSaveLoc, mbItemRect, and mbUglyScroll stuff
  494. typedef struct {
  495.     short    lastMBSave;
  496.     long    mbCustomStorage;
  497.     Rect    mbItemRect;            // Greatest item of interest to us currently
  498.     char    mbMenuDelay;
  499.     char    mbMenuDrag;
  500.     short    mbUglyScroll;        // Of semi-interest (tho what it does I don't know)
  501.     short    mbIconState;
  502.     long    mbHeader;            // Actually, size is unknown!
  503. } MBGlobalData;
  504.  
  505. #define mbItemRectOffset    6
  506. #define mbUglyScrollOffset    16
  507.  
  508. #define sgMBSaveLoc            *((Handle*)0x0B5C)
  509. #define sgMBItemRectPtr        ((Rect*)((*sgMBSaveLoc) + mbItemRectOffset))
  510. #define sgMBUglyScrollPtr    ((short*)((*sgMBSaveLoc) + mbUglyScrollOffset))
  511. #define sgHuhRectPtr        ((Rect*)0x09FA)
  512.  
  513. // menuDisable stuff
  514. typedef struct {
  515.     short hiWord;
  516.     short loWord;
  517. } StuffedLong;
  518.  
  519. #define sgMenuDisablePtr    ((StuffedLong*)0x0B54)
  520.  
  521. #endif // USE_UNDOCUMENTED_STUFF
  522.  
  523. // ---------------------------------------------------------------------------
  524.  
  525. /*
  526.     DoChooseMsg.
  527.     This is the only other function which calls DrawMenuItem, other than
  528.     DoDrawMsg. Takes care of the hiliting/unhiliting of menu items.
  529. */
  530.  
  531. void DoChooseMsg(
  532.     MenuHandle    whichMenu,
  533.     Rect        *menuRect,
  534.     Point        hitPt,
  535.     short        *itemID,
  536.     MDEFstuff    *mdefData) {
  537.  
  538.     Str255 itemText;
  539.     short mouseItem;
  540.     
  541.     mouseItem = FindMenuItem(whichMenu, menuRect, hitPt);
  542.  
  543.     if (mouseItem != 0) {
  544.         // Pre-fetch some data we'll need later on (item text)
  545.         GetItem(whichMenu, mouseItem, itemText);
  546.  
  547. #if USE_UNDOCUMENTED_STUFF
  548.         /*
  549.             Boo-hoo-hoo! We need to set the mbItemRect stored in mbSaveLoc.
  550.  
  551.             All UNDOCUMENTED, but REQUIRED if you wish to make your mdef
  552.             work properly with submenus. Thank God for Usenet and sample
  553.             source code! If this is taken out, the submenus flash about
  554.             5 times, cause they get the mDrawMsg 5 times for some reason!
  555.             Thus they erase, redraw 5 times, causing significant flicker.
  556.  
  557.             Yuck.
  558.         */
  559.         Rect itemRect;
  560.         GetMenuItemRect(menuRect, &itemRect, mouseItem);
  561.         *sgMBItemRectPtr    = itemRect;
  562.         
  563.         /*
  564.             Either using the below lines or commenting them out doesn't
  565.             seem to make any difference so far. So the less we muck
  566.             with the system the safer we'll be. Uncomment when the
  567.             purpose(s) are found...
  568.         */
  569.         // *sgMBUglyScrollPtr    = true;
  570.         // *sgHuhRectPtr        = itemRect;    // MenuSelect seems to be needing this
  571. #endif // USE_UNDOCUMENTED_STUFF
  572.     }
  573.  
  574.     InsetRect(menuRect, 1, 1);
  575.     if (mouseItem == 0 ||                        // out of bounds or disabled
  576.         IsItemDisabled(whichMenu, mouseItem)) {            
  577.  
  578.         DrawMenuItem(whichMenu, menuRect, *itemID, kMenuUnhilited, mdefData);
  579.         *itemID = 0;                // return "cancel" code
  580.  
  581.     }
  582.     else if (mouseItem != *itemID) {
  583.         // unhilight previous
  584.         DrawMenuItem(whichMenu, menuRect, *itemID, kMenuUnhilited, mdefData);
  585.         // hilight new
  586.         DrawMenuItem(whichMenu, menuRect, mouseItem, kMenuHilited, mdefData);
  587.         // return new
  588.         *itemID = mouseItem;
  589.         
  590.     }
  591.  
  592. #if USE_UNDOCUMENTED_STUFF
  593.     // Set the MenuDisable low-mem global; whether the
  594.     // item is disabled or not doesn't matter.
  595.     sgMenuDisablePtr->hiWord = (**whichMenu).menuID;
  596.     sgMenuDisablePtr->loWord = mouseItem;
  597. #endif // USE_UNDOCUMENTED_STUFF
  598.  
  599.     InsetRect(menuRect, -1, -1);
  600. } // END DoChooseMsg
  601.  
  602. // ----------------------------------------------------------------------
  603.  
  604. void InitMenuData(short menuID, MDEFstuff *data) {
  605.     MDEFstuff **menuParameters;
  606.     
  607.     FillInColor(&data->white, kWhite, kWhite, kWhite);
  608.     FillInColor(&data->black, kBlack, kBlack, kBlack);
  609.     
  610.     // If an optional 'MnuT' resource exists, which describes the
  611.     // menu color and font usage, load that. Else fill in default
  612.     // values for MDEF.
  613.     menuParameters = (MDEFstuff**)GetResource(kDefaultMDEFparametersType,
  614.         menuID);
  615.     if (menuParameters == NULL) {
  616.         // Can't find an 'MnuT' with same id as menu. Try default 'MnuT' rsrc id...
  617.         menuParameters = (MDEFstuff**)GetResource(
  618.             kDefaultMDEFparametersType, kDefaultMDEFparametersID);
  619.     }
  620.  
  621.     if (menuParameters == NULL) {
  622.         (data->params).menuHiliteColor = data->white;
  623.         FillInColor(&(data->params).menuBkgndColor, kLtGray, kLtGray, kLtGray);
  624.         FillInColor(&(data->params).menuShadowColor, kDkGray, kDkGray, kDkGray);
  625.         (data->params).menuSelectionColor = (data->params).menuShadowColor;
  626.         (data->params).menuFont = kMenuFont;
  627.         (data->params).menuSize = kMenuSize;
  628.         (data->params).menuFace = kMenuFace;
  629.         (data->params).exactWin95Look = false;
  630.     }
  631.     else {
  632.         HLock((Handle)menuParameters);
  633.         BlockMove(*menuParameters, &data->params, sizeof(MDEFparameters));
  634.         HUnlock((Handle)menuParameters);
  635.         ReleaseResource((Handle)menuParameters);
  636.     }
  637. } // END InitMenuData
  638.  
  639. // ---------------------------------------------------------------------------
  640.  
  641. /*
  642.     FillInColor.
  643.     If you use RGBColors, no doubt you'll be using some function similar to this.
  644.     Now why didn't Apple include a function like this? Less overhead, I guess.
  645.  
  646.     Apple should also have included get/set routines for a grafport's txFont,
  647.     txSize, txFace, and txMode. But who's perfect?
  648. */
  649.  
  650. void FillInColor(
  651.     RGBColor *theColor,
  652.     unsigned short r,
  653.     unsigned short g,
  654.     unsigned short b) {
  655.  
  656.     theColor->red   = r;
  657.     theColor->green = g;
  658.     theColor->blue  = b;
  659. } // END FillInColor
  660.  
  661. // ---------------------------------------------------------------------------
  662. // ---------------------------------------------------------------------------
  663.  
  664. // END Windows95 MDEF.cpp